/**
 * Filename: d:\frontend\vue\nuxt-ssr\components\commons\alert\window\window.ts
 * Path: d:\frontend\vue\nuxt-ssr
 * Created Date: Saturday, January 4th 2020, 1:50:11 pm
 * Author: zzp-dog
 * 弹出层window
 * Copyright (c) 2020 Your Company
 */
import Vue, { ComponentOptions } from 'vue';
import Component from 'vue-class-component';
import Default from '../_placeholder/default.vue';
import { Prop, Ref } from 'vue-property-decorator';
/**
 * window组件（弹出层的一种）
 *
 * 可以通过调用静态方法showWindow弹出该组件，
 */
@Component
export default class WindowComponent extends Vue {
    /** 是否进入停留状态 */
    active: boolean = false;
    /** 缩小状态 */
    min = true;
    /** 弹出层引用 */
    @Ref('window') window: any;


    [key: string]: any;

    constructor(options: ComponentOptions<any> | any) {
        super();
    }

    private mounted(): void {
    }

    /**
     * 放大缩小
     * @param e 点击事件
     */
    switchSize(e: any) {
        if (this.min) { // 当前状态为缩小，点击放大
            this.window.style.cssText = 'height:100%;width:100%;top:0;left:0;';
            this.min = false;
            const maximize = this.callback.maximize;
            maximize && maximize();
        } else { // 当前状态为放大，点击缩小
            this.window.style.cssText = this.window._minStyle;
            this.min = true;
            const minimize = this.callback.minimize;
            minimize && minimize();
        }
    }

    /**
     * 点击关闭弹窗
     * @param e 事件
     */
    close(e: any) {
        // 设置关闭时的渐变
        // 将行内top样式消除，使css中离开时的top样式生效，否则trans1和trans2的离开渐变不生效
        this.window.style.cssText = this.window.style.cssText.replace(/top:(.*)?;/,'');
        this.window.style.transition = 'all ' + this.leave / 1000 + 's';
        this.active = false;
        (<any>this.$refs.mask).style.display = 'none';
        // 移除
        setTimeout(() => {
            document.body.removeChild(this.$el);
            const close = this.callback.close;
            close && close(e);

        }, this.leave)
    }

    /**
     * 打开弹窗
     */
    open() {
        // 设置打开时的渐变
        this.window.style.transition = 'all ' + this.enter / 1000 + 's';
        document.body.appendChild(this.$el);
        // 进入激活状态，添加静止时类
        this.active = true;
        // 左右居中，top用css控制
        const w = this.window.offsetWidth;
        const h = this.window.offsetHeight;
        // 当前窗口大小，this.window.parentNode => position:fixed;height:100%;width:100%
        const ww = this.window.parentNode.offsetWidth;
        // 初始定位
        const leftStyle = 'left:' + ((ww - w) / 2) + 'px;';
        this.window.style.cssText += leftStyle;
        // 记录最小化时的样式
        this.window._minStyle = leftStyle + 'width:' + (w + 1) + 'px;height:' + (h + 1) + 'px;';
        // 取消渐变，否则移动会有渐变
        setTimeout(() => {
            this.window.style.transition = 'none';
        }, this.enter)
    }
    /**
     * 阻止拖拽
     * @param e 拖拽事件
     */
    tragstart(e: any) {
        e.stopPropagation();
        e.preventDefault();
        e.returnValue = false;
    }
    /**
     * 开始移动
     * @param e 事件
     */
    start(e: any) {
        if (!this.min) return;
        const point = {
            x: e.pageX || e.clientX,
            y: e.pageY || e.clientY
        }
        const dis = {
            x: this.window.offsetLeft - point.x,
            y: this.window.offsetTop - point.y
        }
        this.window._dis = dis;
        // 浏览器窗体
        window.onmouseup = this.end;
        window.onmousemove = this.move;
    }
    /**
     * 移动
     * @param e 事件
     */
    move(e: any) {
        const point = {
            x: e.pageX || e.clientX,
            y: e.pageY || e.clientY
        };
        let top = point.y + this.window._dis.y;
        let left = point.x + this.window._dis.x;
        // 当前窗口大小，this.window.parentNode => position:fixed;height:100%;width:100%
        const maxx = this.window.parentNode.offsetWidth - this.window.offsetWidth;
        const maxy = this.window.parentNode.offsetHeight - this.window.offsetHeight;
        // 判断是否越界
        if (top <= 0) { // y方向
            top = 0;
        } else if (top >= maxy) {
            top = maxy;
        }
        if (left <= 0) { // x方向
            left = 0;
        } else if (left >= maxx) {
            left = maxx - 1;
        }
        this.window.style.top = top + 'px';
        this.window.style.left = left + 'px';
    }
    /**
     * 停止移动
     * @param e 事件
     */
    end(e: any) {
        window.onmouseup = null;
        window.onmousemove = null;
    }
    /**
     * 弹出pop式弹窗
     * @param options 配置参数
     * @return WindowComponent
     */
    static showWindow(options?: WindowOptions): WindowComponent {
        options = options || <any>{};
        // 默认参数
        const o: any = {
            title: '弹窗',
            animation: 'trans1',
            enter: 200,
            leave: 200,
            isScale: false,
            content: '什么也木有~',
            callback: {},
        }
        Object.assign(o, options);
        const el = document.createElement('div');
        const $options: any = { el, data: o };
        // “投影”内容，默认传入字符串-'什么也没有~'
        const content = o.content;
        if (typeof content === 'function') { // 如果传入组件类
            $options.data.handler = o.handler || {};
            $options.components = { child: content };
        }
        const window = new WindowComponent($options);
        // 进入
        window.open();
        return window;
    }
}

export interface WindowOptions {
    /** 弹窗标题 */
    title?: string;
    /**
     * 动画名称
     * - trans1 从下往上（进入） -> 从下到上（离开）
     * - trans2 从下到上（进入） -> 从下往上（离开）
     * - scale  放大（进入） -> 从下到上（离开）缩小
     */
    animation?: string;
    /** 进入过渡时间 */
    enter?: number;
    /** 离开过渡时间 */
    leave?: number;
    /** 回调 */
    callback?: WindowCallback;
    /** html | 子组件 被ts-loader编译后的 */
    content?: string | Function;
    /** 是否放大缩小 */
    isScale?: boolean;
    /**
     * vue实例句柄 , content组件可通过$attrs.handler拿到这个句柄
     */
    handler?: Vue;
}

/** 回调 */
export interface WindowCallback {
    /** 关闭回调 */
    close?: Function;
    /** 最小化回调 */
    minimize?: Function;
    /** 最大化回调 */
    maximize?: Function;
}
